interface IInfo {
    age: number;
    name: string;
    sex: string;
}
type ReadonlyType<T>= {
    +readonly [P in keyof T]: T[P]
};
// 添加 readonly
type ReadonlyInfo= ReadonlyType<IInfo>;
type RemoveReadonlyType<T>= {
    -readonly [P in keyof T]: T[P]
};
// 去除 readonly
type WithoutReadonluInfo= RemoveReadonlyType<IInfo>;

function mapObject<K extends (string | number), T, U>(obj: Record<K, T>, f: (x: T) => U): Record<K, U> {
    const res: any = {};
    for (const key in obj) {
        if (obj.hasOwnProperty(key)) {
            res[key] = f(obj[key]);
        }
    }
    return res;
}
const names = {0: "hello", 1: "world", 2: "bye"};
// tslint:disable-next-line:max-line-length
// mapObject<(0|1|2), string, number>(obj: Record < (0 | 1 | 2), string > , f: (x: string) => number); : Record < (0 | 1 | 2), number >
// console.log(mapObject(names, (s) => s.length));

// Proxy
interface IProxy<T> {
    get(): T;
    set(value: T): void;
}
// Proxify
type Proxify<T>= {
    [P in keyof T]: IProxy<T[P]>
};
function proxify<T extends object /*extends {booleanhasOwnProperty(): () => boolean}*/>(obj: T): Proxify<T> {
    const result = {} as Proxify<T>;
    for (const key in obj) {
        if (obj.hasOwnProperty(key)) {
            result[key] = {
                get: () => obj[key],
                set: (value) => obj[key] = value,
            };
        }
    }
    return result;
}
// console.log(proxify({
//     age: 18,
//     name: "funqlin",
// }));

function unproxify<T extends object>(t: Proxify<T>): T {
    const result = {} as T;
    for (const key in t) {
        if (t.hasOwnProperty(key)) {
            result[key] = t[key].get();
        }
    }
    return result;
}

// 最后获取类型中所有部位never的属性名
type Type7<T>= {
    [K in keyof T]: T[K] extends Function/*(p: string) => void*/ ? K : never
}[keyof T];
interface IPart {
    id: number;
    name: string;
    subparts: IPart[];
    undatePar(newName: string): void;
}
type test7= Type7<IPart>;

type Type9<T>= T extends Array<infer U>?U: T;
type test5= Type9<string[]>; // string
type test6 = Type9<string>; // string